package com.cheng.gateway;

import java.util.Calendar;
import java.util.Date;
import java.util.Random;

/**
 * 一个接口每分钟允许访问100次
 * 算法解析：
 * 		1、设置一个计数器count，接收一个请求count++且记录当前时间
 * 		2、判断当前时间和上次统计时间是否为同一分钟，如果是同一分钟则判断 count 是否超过阈值，如果超过阈值，则返回限流拒绝。如果不是同一分钟则把 count 重置为1，判断是否超过阈值。
 * 算法缺陷：
 *          1、如果用户请求频率不均匀会导致短时间、高并发的风险（前一分钟和下一分钟的交界处同时出现100个并发请求,此时不会限流,这个时候就是200个并发）。
 * @author cheng-qiang
 * @date 2022年08月29日14:22
 */
public class 计数器算法 {

    // 记录上次统计时间
    static Date lastDate = new Date();
    // 初始化值
    static int counter = 0;

    /**
     * 限流算法之计数器
     * @author cheng-qiang
     * @date 2022/8/29 14:26
     * @return boolean
     */
    static boolean countLimit() {
        Date now = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(now);
        int minute = calendar.get(Calendar.MINUTE);
        calendar.setTime(lastDate);
        int lastMinute = calendar.get(Calendar.MINUTE);
        if (minute != lastMinute) {
            lastDate = now;
            counter = 0;
        }
        ++counter;
        return counter >= 100;
    }

    public static void main(String[] args) {
        for (; ; ) {
            // 模拟一秒
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Random random = new Random();
            int i = random.nextInt(3);
            // 模拟1秒内请求1次
            if (i == 1) {
                if (countLimit()) {
                    System.out.println("限流了" + counter);

                } else {
                    System.out.println("没限流" + counter);
                }
            } else if (i == 2) { // 模拟1秒内请求2次
                for (int j = 0; j < 2; j++) {
                    if (countLimit()) {
                        System.out.println("限流了" + counter);
                    } else {
                        System.out.println("没限流" + counter);
                    }
                }
            } else { // 模拟1秒内请求10次
                for (int j = 0; j < 10; j++) {
                    if (countLimit()) {
                        System.out.println("限流了" + counter);
                    } else {
                        System.out.println("没限流" + counter);
                    }
                }
            }
        }
    }
}
